package cn.kgc.security;

import cn.kgc.entity.CustomerUser;
import cn.kgc.entity.Users;
import cn.kgc.service.MenusService;
import cn.kgc.service.impl.UsersServiceImpl;
import cn.kgc.util.ResultConstant;
import cn.kgc.util.SystemConstant;
import cn.kgc.util.cache.RedisUtil;
import cn.kgc.util.exception.HttpException;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.List;

/**
 * SpringSecurity通过loadUserByUsername方法获取用户信息,比较密码是否正确
 */
@Service("userDetailsService")
public class UsersDetailServiceImpl implements UserDetailsService {
    @Resource
    private UsersServiceImpl usersService;
    @Resource
    private MenusService menusService;
    @Resource
    private RedisUtil redisUtil;

    public UsersDetailServiceImpl(UsersServiceImpl usersService) {
        this.usersService = usersService;
    }

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        //根据用户名查询用户信息
        //将查询出来的用户对应的加密后的密文喝用户登录时输入的原文进行比较，
        // 判断密码是否正确(springSecurity会自动比较)
        LambdaQueryWrapper<Users> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Users::getUserName, username);
        Users users = usersService.getOne(wrapper);
        if (users == null) {
            throw new HttpException(ResultConstant.LOGIN_ERROR);
        }
        //查询用户对应的权限信息(根据用户的角色id查询出角色拥有的所有按钮权限)
        List<SimpleGrantedAuthority> authorities = menusService.getAuthorityByRoleId(users.getRoleId());
        //将权限信息保存到Redis中(注意需要修改用户权限时一定不要忘记清空缓存)
        //todo 修改用户权限时不要忘记删除缓存
        //key 是system:authorities:"用户id
        //values 是权限信息
        redisUtil.set(SystemConstant.REDIS_PREFIX_SYS_AUTHORITY + users.getRoleId(), authorities);
        //返回SpringSecurity用户信息(CustomerUser:用户信息和权限信息)
        return new CustomerUser(users, authorities);
    }
}
